package device

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/astaxie/beego/logs"
	"smart_home/api/utils/mqtt"
	"time"
)

type ICommand interface {
	Parser(m interface{}, action int) error
	SendCommand(sta, payload string, qos int64, retaion bool) error
	SendResult(typ, sta string, action int, result *bool, tasknock interface{}) error
}

type Command struct {
	Type    string `json:"type"`
	Action  int64  `json:"action"`
	Time    int64  `json:"time"`
	Done    string `json:"done"`
	Tasknoc string `json:"tasknoc"` // 任务号
}

const (
	topic_command = "%s/command"
	topic_result  = "%s/command/result"
	CLOSE         = 0
	OPEN          = 1
	INSERT        = 0
	UPDATE        = 1
	DELETE        = 2
	TYPE_SWITCH   = "switch"
	TYPE_TIMING   = "timing"
	TYPE_DELAY    = "delay"
)

// 解析命令
func (c *Command) Parser(m interface{}, action int) error { return nil }

// 发送命令
func (c *Command) SendCommand(sta, payload string, qos int64, retaion bool) error {
	var (
		err        error
		done       chan int
		failMsgErr error = errors.New("操作失败")
	)

	if ! mqtt.IsOnline(sta) {
		err = errors.New("设备离线")
		logs.Debug(err)
		return err
	}

	err = mqtt.Push(fmt.Sprintf(topic_command, sta), payload, qos, false)
	if err != nil {
		// 发送失败时，删除信号源
		DelSign(c.Done)
		logs.Error(err)
		return failMsgErr
	}

	after := time.After(EXPIRE_IN)
	if done, err = GetSign(c.Done); err != nil {
		logs.Error(err)
		return failMsgErr
	}

	select {
	case <-done:
		DelSign(c.Done)
		return nil
	case <-after:
		DelSign(c.Done)
		return errors.New("命令超时")
	}

	return failMsgErr
}

// 发送操作结果
func (c *Command) SendResult(typ, sta string, action int, result *bool, tasknock interface{}) error {

	if ! mqtt.IsOnline(sta) {
		return errors.New("设备离线")
	}

	m := make(map[string]interface{})
	m["type"] = typ
	m["action"] = action
	m["time"] = time.Now().Unix()
	m["tasknock"] = tasknock
	if *result == true {
		m["result"] = 1
	} else {
		m["result"] = 0
	}

	payload, err := json.Marshal(m)
	if err != nil {
		return err
	}

	err = mqtt.Push(fmt.Sprintf(topic_result, sta), string(payload), int64(1), false)
	return err
}
